#pragma once
#include <map>
#include <utility>


template <class T>
class TCollection {
public:
typedef typename std::set<T>::iterator CollectionIter;
typedef typename std::pair<CollectionIter, bool> IterBoolPair;
typedef typename std::pair<CollectionIter, CollectionIter> CollectionPair;

IterBoolPair Add(const T& elem) {
  return collection_.insert(elem);
}

int Delete(const T& elem) {
  return collection_.erase(elem);
}

void Delete(typename std::set<T>::iterator iter) {
  collection_.erase(iter);
}

CollectionPair GetCollection() const {
  return make_pair(collection_.begin(), collection_.end());
}

IterBoolPair Find(const T& elem) const {
  IterBoolPair pair;
  pair.first = collection_.find(elem);
  pair.second = pair.first != collection_.end();
  return pair;
}

IterBoolPair FindByName(const std::string name) const {
  IterBoolPair pair;
  pair.first = find_if(collection_.begin(), collection_.end(), bind2nd(NameEquals(), name));
  pair.second = pair.first != collection_.end();
  return pair;
}

int Count() const {
  return collection_.size();
}

bool Empty() const {
  return collection_.empty();
}

IterBoolPair GetLast() const {
  return make_pair(--collection_.end(), Empty());
}

void Clear() {
  collection_.clear();
}

private:
  friend std::ostream& operator<<(std::ostream& os, const TCollection<T>& collection);
  friend std::istream& operator>>(std::istream& is, TCollection<T>& collection);

  ///
  /// Functor for locating elements by name
  ///
  struct NameEquals : public std::binary_function<T, std::string, bool> {
    bool operator() (const T& obj, const std::string& name) const {
      return obj.name() == name;
    }
  };

  std::set<T> collection_;

};

template <class T>
std::ostream& operator<<(std::ostream& os, const TCollection<T>& collection) {
  TCollection<T>::CollectionPair iters = GetCollection();
  for (; iters.first != iters.second; ++iters.first)
    os << *iters.first;
  return os;
}

template <class T>
std::istream& operator>>(std::istream& is, TCollection<T>& collection) {
  T elem;
  is >> elem;
  return is;
}